查看原文
其他

00 后架构师,那可能么?

鱼皮 程序员鱼皮 2024-01-21

大家好,我是鱼皮,这篇文章我们来聊一个听起来很高大上、实则并不难的知识 —— 架构设计

这是技术方向的朋友们必须要 重点掌握 的内容,也是企业级项目在前期准备阶段必须要做的核心工作!

这篇文章中,我会结合之前开发 鱼聪明 AI 的实践经验,依次给大家分享:什么是架构设计?为什么要做架构设计?怎么做好架构设计?

一、什么是架构设计?

想象一下,如果现在我们要盖一座摩天大楼,需要做哪些事?

是直接让工人去搬砖、叠砖么?还是让挖掘机来挖呀挖呀挖?

当然不是!

在盖楼之前,肯定会有一名建筑师,根据大楼的实际用途、地理位置、入驻需求等信息来绘制一份蓝图,蓝图上会规划大楼的外形、内部布局、结构细节等。

绘制好蓝图后,建筑师还要确定每层楼房的框架和支撑结构,确保它们足够稳定,不会说风一吹就塌了。

之后,建筑师还要根据大楼的实际用途和需求来规划每个楼层的用途,比如 B1 层卖小吃、1 层卖服装奢侈品等等。这些都是在大楼动工前确认好的,不会说等工人已经搬好砖后,上面临时决定 “这一层我们不盖了!”。

做软件(网站)开发也是一样,在我们 “码农” 实际动手写代码前,往往会有一个经验丰富的架构师,先绘制一份 架构设计图 ,规划好整个系统的全貌、系统规模、系统的结构。

架构师还要将系统按照功能和需求划分为各个模块,比如商城系统划分为用户模块、商品模块、订单模块等。并且确定各个模块的作用和交互协作方式,保证整个系统能够正常运作。不会出现一个功能故障,整个系统全部瘫痪的情况。

有朋友可能会问了,那架构设计和之前讲过的技术选型有什么区别呢?

还是拿盖楼来举例,其实很好区分。架构设计是规划如何盖楼、每层楼怎么安排;而技术选型是在完成架构设计之后,选择具体用什么材料、工具或方法来完成盖楼。二者是相辅相成的。

用一句话来概括, 架构设计是构建稳固、可靠和可扩展系统的过程

而我们熟知的岗位 “架构师”,就是负责完成系统架构设计,确保系统稳固、可靠、可扩展的人。

在大家的印象里,可能觉得架构师是很高大上的角色。但我个人认为,只要你能够独立完成一个系统的架构设计,能够把复杂的系统拆分为模块化、可扩展的组件,你就已经是架构师了。

所以别说什么 97 年架构师,00 后成为架构师都是合理性的,只不过你能处理的系统范围有限罢了。

二、为什么要做架构设计?

其实从上面盖楼的例子中,相信大家已经能大致感受到架构设计的重要性了。

如果在盖楼前,不先设计好大楼的结构,那么就难以保证大楼的安全和稳定性,风一吹整层楼就塌了。同理,在开发网站前,如果不先设计好网站的整体架构(比如不添加防火墙),后面可能一遇到网络攻击,整个系统就都无法访问了。这是架构设计的核心目标:保证系统地 稳定性、可靠性和可用性 。换句话说,起码要让系统能跑。

不过没关系,系统和人只要有一个能跑就行。

进行架构设计的另一个重要原因,是系统的 可扩展性 。打个比方,建好的商场大楼非常受欢迎,我们想在盖好的大楼上再增加几层楼,那么必须在最初就确保大楼的结构可以支撑额外的重量、能够线性地往上叠加。而不是像下图一样:

同理,如果想要网站能够应对日益增长的用户量和新业务功能,也必须有一个良好的架构设计来支持。不要出现网站用户数增多后,网站无法访问的情况。

此外,好的架构设计也能够提升系统的性能和用户体验。比如在商场内,合理安排电梯数和电梯的位置,就能帮助用户快速到达想去的店铺;而网站的架构设计如果合理,比如用更少的分层完成同样的功能,那么就能更快地响应用户的操作。

总之,想要让网站像摩天大楼一样支棱起来,前期的架构设计是必要的!

三、怎么做好架构设计?

“能完成架构设计” 和 “能做好架构设计” 还是有很大的区别的,下面我会结合自己多年的学习经验、以及鱼聪明 AI 的架构设计,分享一些我认为的做好架构设计的关键。

掌握方法论

做好架构设计的前提是具备一定的理论知识。所谓方法论,是指前人通过总结和归纳形成的一套 特定问题的解决方案 。就像我们做数学题的时候知道套用公式来解题一样。

有很多对架构设计有帮助的方法论。比如初学编程时接触到的面向对象设计,软件开发基本原则、23 种经典设计模式、SOA 面向服务架构、DDD 领域驱动设计等等。掌握这些方法论背后的思想,是做好架构设计的 前提

举个例子,面向对象设计的五个基本原则 SOLID 中,有一点是 单一职责原则 ,是指:一个类或模块应该有且只有一个单一的责任,每个类或模块应该只关注于一个特定的功能或职责。换句话说,每个模块应该只做好自己的事。

我们在进行鱼聪明 AI 网站的架构设计时,首先就遵循了单一职责原则,将系统 按照功能拆分 为用户模块、助手模块、对话模块、绘画模块、支付模块等。这样一来,当我们想要扩展对话相关的功能时,就不用改动助手模块的代码。也可以将不同的模块交给团队中不同的同学进行开发。

学习经典架构

前人栽树,后人乘凉。在我们没有能力自主设计一套架构前,不妨站在巨人的肩膀上,学习一些前人总结和实践过的经典架构。

简单举几个例子:

1)分层架构

首先是最经典的分层架构,把系统分为多个不同的层,每一层都有特定的功能和职责,且只和自己的直接上层与直接下层 “打交道”。

比如开发 Java 企业级后端项目时常用的三层架构,将系统分为表示层、业务逻辑层、数据访问层。

表示层负责接受用户请求,把用户输入的参数传递给业务逻辑层进行处理,并返回数据、页面等内容给用户。

业务逻辑层负责处理复杂的业务逻辑,比如调用 AI 能力完成智能对话、再进行加工处理、调用数据访问层将结果存到数据库中,也是我们做系统主要开发的部分。

数据访问层负责操作底层的数据源,比如对数据库、文件、缓存等进行增删改查。

分层架构的适用性非常广泛,绝大多数企业级系统都可以把分层架构作为基础的架构设计。

计算机网络也是采用了经典的分层架构,OSI 七层参考模型中,把计算机网络自底向上分为了物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。每个层只处理特定的功能,比如数据传输、数据的路由;层与层之间通过接口(或者叫协议)进行通信。

我们的鱼聪明 AI 后端也是使用了分层架构,只不过在原有的三层架构基础上,在业务逻辑层和数据访问层之间又增加了 Manager 层(通用逻辑层),将业务逻辑层经常调用的 公共逻辑 提取出来,便于复用。

2)微服务架构

微服务的 “微” 是相对于 “单体” 项目的概念。微服务架构是指将完整的大型系统拆分为多个微小的、自治的服务,每个服务都能独立部署、独立扩展和维护、互不影响,服务之间通过网络通信进行协作,从而实现原本大型系统的完整功能。

我们的鱼聪明 AI 就用到了微服务架构。前面也提到了,我们首先将系统按照功能划分为了多个模块。

但如果我们只是按逻辑划分出了这些模块,实际上所有的代码仍然部署在同一个项目中,打包后仍然是一个可执行文件。那么所有模块要么都在运行、要么都在宕机,本质上还是单体项目。一个服务崩了,可能导致整个项目都无法运行!

所以我们将部分重要模块(比如支付模块)的代码从原本项目中抽离,单独作为了一个服务,并且还启动了备份,从而保证了支付业务的稳定性。说什么也不能影响收入对不对~

能够实现微服务设计的框架也很多,比如 Java 的 Spring Cloud、Apache Dubbo 等。但是学习微服务更重要的是思想,即 如何合理地拆分服务

并不是所有的项目都要把所有功能都拆分成子服务的,像我们的鱼聪明 AI,也没有把用户模块和助手模块进行分离,原因是这两个模块的业务都不复杂、并且存在紧密的依赖,拆分后反而不利于维护了。

3)事件驱动架构

在事件驱动架构中,各模块之间是通过事件(或者消息)的 发布订阅模型 进行通信的。

举个最简单的例子,有两个模块:支付模块和会员模块,当用户支付成功后,支付模块会给会员模块发送一个 “XX 用户支付成功” 的事件,会员模块收到这个时间后,给对应的用户开通会员即可。

但实际运用时,事件驱动架构往往会引入一个 事件总线 ,相当于一个中介,负责集中收集和下发事件。

比如鱼聪明 AI 的对话功能和绘画功能就采用了事件驱动架构。当上游返回 AI 回复的消息或生成的图片后,会发送 “成功” 消息到事件总线,然后事件总线再将这些消息分别转发给对应的模块去处理。如下图:

这样一来,各模块之间就实现了解耦(互不影响)。假如后续我想新增多个对话模块,只要将该模块和事件总线建立连接即可,不会影响到其他模块的运行。

关注需求和痛点

我们在学习过程中接触到的项目,几乎都可以套用上述几种主流的架构。但具体应该如何做好架构设计,一定是要结合实际的需求和要解决的痛点去分析。

以鱼聪明 AI 为例,前面也提到了,我们首先就按照需求(功能)将系统拆分为了多个模块,然后将部分模块单独封装为服务进行独立部署。

但架构设计并没有到此结束,接下来分析下我们这个网站的痛点,主要是 “安全性” 和 “访问互通性” 这两个方面。

安全性

根据我之前的翻车经历,网站上线后一定会遭受各种攻击!所以,我们在原有的分层架构基础上进行扩展,在表示层前增加高防服务器和 Nginx 防火墙,在表示层后增加了分布式限流和权限校验处理。

在表示层前添加集中的分布式限流和权限校验处理也是合理的,以实际需求为主。

改进过后的架构如图:

如果用户在短时间内用不法手段频繁向系统发送请求,那么在限流层就会被拦截,不会进行后续的业务逻辑处理。

访问互通性

我们的 AI 绘画模块需要依赖第三方服务来完成部分功能,但是第三方服务并不支持访问跨地区访问,网络无法互通,怎么办呢?

这时,我们有 2 个方案可选:

1)把整个系统都放到第三方服务所在的地区去部署。如下图:

2)在 AI 绘画模块和第三方服务之间搭建一个代理,让代理帮忙发送和响应请求。如下图:

如果是你的话,会选择哪个呢?

方案 1 的好处是方便,但缺点也很明显,整个系统都移到其他地区,也就意味着原本地区的用户访问系统的所有功能,速度都会变慢。

方案 2 的好处是只需要改变 AI 绘画模块发送的请求地址信息,而系统的其他功能(比如查询用户信息)性能完全不变;缺点就是要搭建额外的服务、增加了实现成本。

最终,我们选择了方案 2 并改进了架构设计,增加一点实现成本来换取更好的用户体验。

通过这个例子,我想告诉大家的是:没有绝对完美的架构设计 。和技术选型一样,我们做架构设计的目标是寻找实际情况下的最优解。

超前思考

我们在做架构设计时,要养成超前思考的习惯,不能只针对现状,而是要提前预见系统未来可能的发展,预留足够的 可扩展 空间。

比如我们的鱼聪明 AI,虽然在最开始只有 100 个内测用户,但我们会按照 1 万个、甚至 10 万个用户的标准去设计系统,所以使用了分布式存储中间件而不是本地服务器来存储用户登录 Session;虽然早期历史对话消息数只积累了 5 万条,但我们提前设计了消息过期淘汰机制、并且将消息模块解耦,防止消息数达到百万、千万时影响系统的查询性能。

当然,超前思考也要有个度。要避免过度设计,不要提前去考虑绝对不可能发生的事情、不要提前去消耗远超增长的成本。



最后,要注意的是, 架构设计是一个持续的过程 ,要根据业务的实际情况不断优化迭代。比如发现业务收益不高时,通过简化架构来降低成本;业务高速发展时,及时扩容服务来应对增长。

以上,希望大家在之后的学习和做项目的过程中,都能尝试自主设计一套架构。只要有架构设计的意识和足够的积累,人人都能成为架构师!

往期推荐

鱼皮原创实战项目教程【系列】

如何打造出色的求职简历?

我坚持 3 年了!

看完这个,我直接把 SQL 刷通了!

说说我最近招人的感受。。

什么是负载均衡?

继续滑动看下一个

00 后架构师,那可能么?

鱼皮 程序员鱼皮
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存